Skip to content

Conversation

@TheLydonKing
Copy link
Collaborator

Release Notes:

  • Removed overloaded methods and introduced AuthMethod trait to indicate authentication method. This removes ambiguity with the default parameters and avoids compilation errors.

Closes: #154

@TheLydonKing TheLydonKing self-assigned this Dec 3, 2025
@TheLydonKing TheLydonKing requested a review from dk1844 as a code owner December 3, 2025 09:38
@TheLydonKing TheLydonKing added the enhancement New feature or request label Dec 3, 2025
@github-actions
Copy link

github-actions bot commented Dec 3, 2025

Report: Report: clientLibrary - scala:2.12.17

Metric (instruction) Coverage Threshold Status
Overall 49.61% 43.0%
Changed Files 62.64% 70.0%
File Path Coverage Threshold Status
AuthMethod.scala 100.0% 0.0%
TokenRetrievalClient.scala 25.28% 0.0%

Copy link
Collaborator

@dk1844 dk1844 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is nice, but with a library we should meet additional standards (see comments below)

*/
def fetchRefreshToken(username: String, password: String): RefreshToken = {
fetchAccessAndRefreshToken(username, password, List.empty, false)._2
def fetchRefreshToken(authMethod: AuthMethod): RefreshToken = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither the new method nor the existing (which should be present for some time as described above) seem to be covered with unit tests.

That is unfortunate, because the appropriate class TokenRetrievalClientTest already exists and it would be nice to have it covered. I see two options:

  1. You may need to mock the creation of RestTemplate & KerberosRestTemplate (could be done by moving the creation to a method that you override in the test) to write the unit test properly.
  2. A half-measure would be just to mock the fetchToken methods in the class to check if those are receiving expected parameters. Not a complete unit test, but even this would be better than nothing if the option 1 cannot be reasonably done (I believe it should be).

@TheLydonKing TheLydonKing requested a review from dk1844 January 26, 2026 12:34
Comment on lines +23 to +74
class MockableTokenRetrievalClient(
host: String,
restTemplate: RestTemplate,
kerberosRestTemplate: KerberosRestTemplate) extends TokenRetrievalClient(host) {

override private[client] def fetchToken(issuerUri: String, username: String, password: String): String = {
val response: ResponseEntity[String] = restTemplate.exchange(
issuerUri,
HttpMethod.POST,
null,
classOf[String])
response.getBody
}

override private[client] def fetchToken(
issuerUri: String,
keyTabLocation: Option[String],
userPrincipal: Option[String]): String = {
val response: ResponseEntity[String] = kerberosRestTemplate.exchange(
issuerUri,
HttpMethod.POST,
null,
classOf[String])
response.getBody
}

override def refreshAccessToken(
accessToken: AccessToken,
refreshToken: RefreshToken): (AccessToken, RefreshToken) = {
val issuerUri = s"$host/token/refresh"
val jsonPayload: JsonObject = new JsonObject()
jsonPayload.addProperty("token", accessToken.token)
jsonPayload.addProperty("refresh", refreshToken.token)

val headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON))

val requestEntity = new HttpEntity[String](jsonPayload.toString, headers)

val response: ResponseEntity[String] = restTemplate.exchange(
issuerUri,
HttpMethod.POST,
requestEntity,
classOf[String]
)
val jsonObject = JsonParser.parseString(response.getBody).getAsJsonObject
(
AccessToken(jsonObject.get("token").getAsString),
RefreshToken(jsonObject.get("refresh").getAsString)
)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are already providing the mocked exchange templates, I assume you want the full solution. Good choice.

However, you do not need to override all the fetchToken and refreshAccessToken (also these should be rather tested, not overridden). I think all you need is this:

Suggested change
class MockableTokenRetrievalClient(
host: String,
restTemplate: RestTemplate,
kerberosRestTemplate: KerberosRestTemplate) extends TokenRetrievalClient(host) {
override private[client] def fetchToken(issuerUri: String, username: String, password: String): String = {
val response: ResponseEntity[String] = restTemplate.exchange(
issuerUri,
HttpMethod.POST,
null,
classOf[String])
response.getBody
}
override private[client] def fetchToken(
issuerUri: String,
keyTabLocation: Option[String],
userPrincipal: Option[String]): String = {
val response: ResponseEntity[String] = kerberosRestTemplate.exchange(
issuerUri,
HttpMethod.POST,
null,
classOf[String])
response.getBody
}
override def refreshAccessToken(
accessToken: AccessToken,
refreshToken: RefreshToken): (AccessToken, RefreshToken) = {
val issuerUri = s"$host/token/refresh"
val jsonPayload: JsonObject = new JsonObject()
jsonPayload.addProperty("token", accessToken.token)
jsonPayload.addProperty("refresh", refreshToken.token)
val headers = new HttpHeaders()
headers.setContentType(MediaType.APPLICATION_JSON)
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON))
val requestEntity = new HttpEntity[String](jsonPayload.toString, headers)
val response: ResponseEntity[String] = restTemplate.exchange(
issuerUri,
HttpMethod.POST,
requestEntity,
classOf[String]
)
val jsonObject = JsonParser.parseString(response.getBody).getAsJsonObject
(
AccessToken(jsonObject.get("token").getAsString),
RefreshToken(jsonObject.get("refresh").getAsString)
)
}
class MockableTokenRetrievalClient(
host: String,
restTemplate: RestTemplate,
kerberosRestTemplate: KerberosRestTemplate) extends TokenRetrievalClient(host) {
override def createRestTemplate(): RestTemplate = restTemplate
override def createKerberosRestTemplate( /* opt params or two methods? */ ): KerberosRestTemplate = kerberosRestTempl

while updating the with

case class TokenRetrievalClient(host: String) {

  private[client] def createKerberosRestTemplate( /* opt params or two methods? */ ): KerberosRestTemplate = {
    new KerberosRestTemplate( /* opt params?*/)
  }

  private[client] def createRestTemplate(): RestTemplate = {
    new RestTemplate()
  }

// and wherever the `new RestTemplate()` or `new KerberosRestTemplate(...)` is used within `TokenRetrievalClient`, you replace it with the methods above.

This way, you only override the very minimal to get your exchange mocks in -- while the rest of the TokenRetrievalClient stays original as is correctly subjected to unit testing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request tested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Set Groups and Case sensitivity for token retrieval in client lib as optional

3 participants